package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.exception.SetmealEnableFailedException;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;

@Service
public class SetmealServiceImpl implements SetmealService {
    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private SetmealDishMapper setmealDishMapper;

    @Override
    @Transactional
    @CacheEvict(cacheNames = "setmeal",key = "#setmealDTO.categoryId")
    public Result addSetmeal(SetmealDTO setmealDTO) {
        //1. 保存套餐
        // 创建一个新的套餐对象
        Setmeal setmeal = new Setmeal();
        // 将传入的数据传输对象（DTO）的属性复制到套餐对象中
        BeanUtils.copyProperties(setmealDTO,setmeal);
        // 将新创建的套餐对象保存到数据库中
        setmealMapper.insert(setmeal);
        //2. 保存套餐里关联的菜品
        // 获取套餐中关联的菜品列表
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        // 检查套餐中是否有关联的菜品
        if (setmealDishes!= null && setmealDishes.size()>0) {
            // 遍历关联的菜品列表，将每个菜品关联到新创建的套餐上
            setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmeal.getId()));
            // 批量将关联的菜品保存到数据库中
            setmealDishMapper.batchinsert(setmealDishes);
        }
         // 返回操作成功的结果
        return Result.success();
    }

    @Override
    public Result querySetmealByPage(SetmealPageQueryDTO setmealPageQueryDTO) {
        //1. 开启分页
        PageHelper.startPage(setmealPageQueryDTO.getPage(),setmealPageQueryDTO.getPageSize());
        //2. 查询列表
        Page<SetmealDTO> page = setmealMapper.selectByPage(setmealPageQueryDTO);
        //3. 封装结果
        PageResult result = new PageResult(page.getTotal(),page.getResult());
        return Result.success(result);
    }

    @Override
    @Transactional
    @CacheEvict(cacheNames = "setmeal",allEntries = true)
    public Result batchDeleteSetmealsByids(List<Long> ids) {
        //1. 如果有某个套餐是“起售”状态，则不允许删除
        // 查询处于“起售”状态的套餐数量
        int count = setmealMapper.selectEnanbleSetmealsCount(ids);
        // 如果存在处于“起售”状态的套餐，则抛出异常
        if (count > 0) {
            throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
        }
        //2. 删除套餐
        // 批量删除套餐数据
        setmealMapper.batchDeleteByIds(ids);
        //3. 删除套餐关联的菜品
        // 批量删除与套餐相关联的菜品数据
        setmealDishMapper.batchDeleteBySetmealIds(ids);
        // 返回删除成功的结果
        return Result.success();
    }

    @Override
    public Result querySetmealById(Integer id) {
        //查询套餐信息
        Setmeal setmeal = setmealMapper.selectById(id);
        //查询套餐关联的菜品列表
        List<SetmealDish> setmealDishes = setmealDishMapper.selectBySetmealId(id);
        //封装成VO对象
        SetmealVO vo = new SetmealVO();
        BeanUtils.copyProperties(setmeal,vo);
        vo.setSetmealDishes(setmealDishes);
        return Result.success(vo);
    }

    @Override
    @Transactional // 声明此方法应在事务中执行
    @CacheEvict(cacheNames = "setmeal",key ="#setmealDTO.categoryId" )
    public Result updateSetmeal(SetmealDTO setmealDTO) {
        // 修改套餐信息
        // 创建一个新的 Setmeal 对象
        Setmeal setmeal = new Setmeal();
        // 将 setmealDTO 对象的属性复制到 setmeal 对象中
        BeanUtils.copyProperties(setmealDTO,setmeal);
        // 通过 setmealMapper 更新数据库中的套餐信息
        setmealMapper.updateById(setmeal);

        // 删除套餐关联的菜品
        // 通过 setmealDishMapper 批量删除与给定套餐 ID 关联的菜品
        setmealDishMapper.batchDeleteBySetmealIds(Collections.singletonList(setmealDTO.getId()));
        // 重新添加套餐关联的菜品
        // 获取套餐 DTO 中的关联菜品列表
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes(); // 如果关联菜品列表不为空
        if (!CollectionUtils.isEmpty(setmealDishes)) {
            // 将每个关联菜品的套餐 ID 设置为当前套餐的 ID
            setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmeal.getId()));
            // 通过 setmealDishMapper 批量插入关联菜品到数据库中
            setmealDishMapper.batchinsert(setmealDishes);
        }
        return Result.success();
    }

    @Override
    @CacheEvict(cacheNames ="setmeal" ,allEntries = true)
    public Result updateStatus(Integer status, Long id) {
        //起售套餐时，如果包含了“停售”状态的菜品，则不允许起售
        if (StatusConstant.ENABLE.equals(status)) { // 如果状态为启用状态
            // 查询套餐关联的所有菜品
            List<Dish> dishes = setmealMapper.selectBySetmeamlId(id);
            //如果有任意一个菜品是“停售”状态，就抛出异常
            //将菜品表转换为流，并过滤"停售的菜品" 统计数量
            Long count = dishes.stream()
                    .filter(dish -> dish.getStatus().equals(StatusConstant.DISABLE))
                    .count();

            // 如果存在状态为“停售”的菜品
            if (count >0) {
                throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
            }
        }
        Setmeal setmeal = new Setmeal();
        setmeal.setId(id);
        setmeal.setStatus(status);
        setmealMapper.updateById(setmeal);
        return Result.success();
    }

    @Override
    @Cacheable(cacheNames = "setmeal",key = "#categoryId")
    public List<Setmeal> list(Integer categoryId) {
        List<Setmeal> setmeals = setmealMapper.selectEnableListByCategoryId(categoryId);
        return setmealMapper.selectEnableListByCategoryId(categoryId);
    }
}
